#!/bin/bash
################################################################################
# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The OpenAirInterface Software Alliance licenses this file to You under 
# the Apache License, Version 2.0  (the "License"); you may not use this file
# except in compliance with the License.  
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
# For more information about the OpenAirInterface (OAI) Software Alliance:
#      contact@openairinterface.org
################################################################################

# file run_mme
# brief run script for MME.
# author  Lionel GAUTHIER
# company Eurecom
# email:  lionel.gauthier@eurecom.fr 


################################
# include helper functions
################################
THIS_SCRIPT_PATH=$(dirname $(readlink -f $0))
source $THIS_SCRIPT_PATH/../build/tools/build_helper
declare -i g_run_msc_gen=0
declare    g_msc_dir="/tmp"
declare    g_mme_default_config_file="/usr/local/etc/oai/mme.conf"
declare    g_mme_default_fqdn=`hostname`".openair4G.eur"

set_openair_env 


function help()
{
  echo_error " "
  echo_error "Usage: run_mme [OPTION]..."
  echo_error "Run the MME executable."
  echo_error " "
  echo_error "Options:"
  echo_error "Mandatory arguments to long options are mandatory for short options too."
  echo_error "  -c, --config-file     file_abs_path Config file to be used by MME if you don't want to use the default one: $g_mme_default_config_file"
  echo_error "  -e, --enable-core-dump              Enable core dump for mme executable"
  echo_error "  -D, --disable-core-dump             Disable core dump for mme executable"
  echo_error "  -d, --daemon                        Run MME as a daemon."
  echo_error "  -g, --gdb                           Run with GDB."
  echo_error "  -G, --gdb-cmd         cmd cmd_arg   Append this GDB cmd to GDB command file (ex1: break Attach.c:272, ex2: watch 0xffee0002)."
  echo_error "                                      All repetitions of this argument are valid."
  echo_error "  -h, --help                          Print this help."
  echo_error "  -k, --kill                          Kill all running MME instances, exit script then."
  echo_error "  -m, --mscgen          directory     Generate mscgen output files in a directory"
  echo_error "  -s, --set-virt-if                   Set virtual interfaces if any listed in config file (default or provided with -c option)"
  echo_error "  -v, --verbosity-level               Verbosity level (0,1,2)."
  echo_error "                                        0 -> ASN1 XER printf off"
  echo_error "                                        1 -> ASN1 XER printf on and ASN1 debug off"
  echo_error "                                        2 -> ASN1 XER printf on and ASN1 debug on"
}

function do_msc_gen()
{
  cd $g_msc_dir
  $THIS_SCRIPT_PATH/msc_gen
}

function control_c()
# run if user hits control-c
{
  echo_warning "\nExiting by ctrl+c\n"
  if [ $g_run_msc_gen -eq 1 ]; then 
    do_msc_gen
  fi
  exit $?
}

function main()
{
  local -i run_gdb=0
  local -i run_daemon=0
  local -i set_virt_nw_if=0
  local    exe_arguments=" "
  local    mme_config_file=$g_mme_default_config_file
  local -a gdb_args
  local -i gdb_index=0

  until [ -z "$1" ]
    do
    case "$1" in
      -c | --config-file)
        mme_config_file=$2
        echo "setting config file to: $mme_config_file"
        shift 2;
        ;;
      -e | --enable-core-dump)
        # https://developer.toradex.com/knowledge-base/enable-and-analyze-coredumps-in-linux
        # Warning for Ubuntu apport should be disabled, should be same for other distro similar services
        core_dump_enabled=$(cat /boot/config-`uname -r` | grep CONFIG_COREDUMP | cut -d '=' -f2)
        if [[ $core_dump_enabled != 'y' ]]; then
          echo_error "Core dumps not enabled for this kernel"
        else
          $SUDO sysctl -w kernel.core_uses_pid=1
          $SUDO sysctl -w kernel.core_pattern='/var/crash/core-%e-%s-%u-%g-%p-%t'
          $SUDO sysctl -w fs.suid_dumpable=2
        
          ulimit -S -c 0
          ulimit -S -c unlimited /usr/local/bin/mme
          echo "Enabled core dump for mme executable"
        fi
        shift;
        ;;
      -D | --disable-core-dump)
        ulimit -S -c 0 /usr/local/bin/mme
        shift;
        ;;
      -d | --daemon)
        run_daemon=1
        shift;
        ;;
      -g | --gdb)
        run_gdb=1
        echo "setting GDB flag to: $run_gdb"
        shift;
        ;;
      -G | --gdb-arg)
        run_gdb=1
        gdb_args[$gdb_index]="$2 $3"
        echo "Appending gdb args: ${gdb_args[$gdb_index]}"
        gdb_index=$((gdb_index + 1))
        shift 3;
        ;;
      -h | --help)
        help
        return 0
        ;;
      -k | --kill)
        $SUDO killall -q mme
        $SUDO rm /var/run/mme*.pid
        return 0
        shift;
        ;;
      -m | --mscgen)
        g_msc_dir=$2
        if [ -d  "$g_msc_dir" ]; then
          echo "setting mscgen log files to dir: $g_msc_dir"
          g_run_msc_gen=1
          shift 2;
        else
          echo_error "Mscgen log dir does not exist"
          return -1
        fi
        ;;          
      -s | --set-virt-if)
        set_virt_nw_if=1
        shift;
        ;;
      -v | --verbosity-level)
        local verbosity_level=$2
        echo "setting verbosity level to: $verbosity_level"
        exe_arguments="-v $verbosity_level $exe_arguments"
        shift 2;
        ;;
      *)   
        echo "Unknown option $1"
        help
        return 1
        ;;
    esac
  done

  set_openair_env 
  cecho "OPENAIRCN_DIR    = $OPENAIRCN_DIR" $green

  #####################################
  # Install config files
  #####################################
  if [ ! -f $mme_config_file ]; then 
    if [ $g_mme_default_config_file != $mme_config_file ]; then
      echo_error "Please provide -c|--config-file valid argument (\"$mme_config_file\" not a valid file)"
      return 1
    fi
  fi

  #####################################
  # Check executables
  #####################################
  if [ ! -e /usr/local/bin/mme ]; then
    echo_error "Cannot find /usr/local/bin/mme executable, have a look at the output of build_mme executable"
    return 1
  fi

  ##########################
  # INSTANCE
  ##########################
  instance_string="INSTANCE"
  instance="`cat $mme_config_file | cut -d "#" -f1 | grep $instance_string | tr -d " " | grep "="`"
  eval $instance
  INSTANCE=${!instance_string}

  #####################################
  # Set virtual network interfaces if requested
  #####################################
  if [ $set_virt_nw_if -eq 1 ]; then 
    set_cn_virtual_interfaces $mme_config_file
    ret=$?;[[ $ret -ne 0 ]] && echo_error "Failed to set virtual interfaces" && return $ret
  fi

  #####################################
  # Clean old MSC generated files
  #####################################
  if [ $g_run_msc_gen -eq 1 ]; then 
    $SUDO rm -f /tmp/openair.msc.*
  fi


  #####################################
  # Running executable
  #####################################
  exe_arguments="-c $mme_config_file $exe_arguments"

  if [ $run_daemon -eq 1 ]; then 
    $SUDO daemon --env="CONFIG_FILE=$mme_config_file" --name=mme$INSTANCE --stdout=/tmp/mmed"$INSTANCE"_stdout.log --stderr=/tmp/mmed"$INSTANCE"_stderr.log --pidfile=/tmp/mmed"$INSTANCE".pid -X /usr/local/bin/mme
    ret=$?
    [[ $ret -ne 0 ]] && return $ret
    if [ $run_gdb -ne 0 ]; then 
      # trap keyboard interrupt (control-c) is done by gdb
      $SUDO touch      .gdb_mmed
      $SUDO chmod 777  .gdb_mmed
      
      $SUDO echo "set target-async on" > .gdb_mmed
      $SUDO echo "set pagination off" >> .gdb_mmed
      mmed_pid=`pidof -s mme`
      $SUDO echo "attach $mmed_pid"  >> .gdb_mmed
      for i in ${!gdb_args1[@]}; do
        $SUDO echo "${gdb_args1[i]} ${gdb_args2[i]}" >> .gdb_mmed
      done
      $SUDO echo "continue"    >> .gdb_mmed
      $SUDO cat .gdb_mmed
      $SUDO gdb -n -x .gdb_mmed
    fi
  else
    if [ $run_gdb -eq 0 ]; then 
      # trap keyboard interrupt (control-c)
      trap control_c SIGINT
      $SUDO mme  `echo $exe_arguments` 2>&1 
    else
      # trap keyboard interrupt (control-c) is done by gdb
      $SUDO touch      ~/.gdb_mme
      $SUDO chmod 777  ~/.gdb_mme
      $SUDO echo "file mme" > ~/.gdb_mme
      $SUDO echo "set args $exe_arguments "        >> ~/.gdb_mme
      for i in `seq 0 $gdb_index`; do
        $SUDO echo "${gdb_args[$i]}"               >> ~/.gdb_mme
      done
      $SUDO echo "run"                             >> ~/.gdb_mme
      $SUDO cat ~/.gdb_mme
      $SUDO gdb -n -x ~/.gdb_mme
      if [ $g_run_msc_gen -eq 1 ]; then 
        #$SUDO do_msc_gen
        cd $g_msc_dir
        $SUDO $THIS_SCRIPT_PATH/msc_gen --profile MME --dir $g_msc_dir --type png
      fi
    fi
  fi
  return $?
}

main "$@"
